package cobots.swarm.agents;

import java.awt.geom.Point2D;

import java.util.Random;

import cobots.swarm.main.MainSwarmClass;
import cobots.swarm.main.SwarmState;
import cobots.swarm.props.PropertiesClass;


public abstract class Agent extends Point2D {

	protected double x,y,mass,absorption;
	protected short id;
	protected static Random random = new Random(System.currentTimeMillis());
	public double R = PropertiesClass.getRmean();
	protected float randHeading = (float) (random.nextGaussian()*Math.PI * 2);	
	protected float randVelocity = 0;
	protected static double cprob = PropertiesClass.getCprob();
	//protected static boolean idleWhenNoComm = PropertiesClass.getidleWhenNoComm();
	protected static final double turnRandomization = PropertiesClass.getturnRandomization();
	protected static final double speedRandomization = PropertiesClass.getspeedRandomization();
	protected static final double randomBehaviorProb = PropertiesClass.getrandomBehaviorProb();
	protected long interactCounter = 0;
	
	public Agent(double x, double y, double mass, double absorption) {
		this.x = x;
		this.y = y;
		this.mass = mass;
		this.absorption = absorption;
	}
	
	public Point2D computeMovement() {
	return idleMovement();
	}
	
	public short getId() {
        return id;
    }

    public void setId(short id) {
        this.id = id;
    }

    @Override
	public double getX() {
		return x;
	}

	@Override
	public double getY() {
		return y;
	}

	public double getMass() {
		return mass;
	}

	public void setMass(double mass) {
		this.mass = mass;
	}
	
	public double getAbsorption() {
		return absorption;
	}

	public void setAbsorption(double absorption) {
		this.absorption = absorption;
	}

	@Override
	public void setLocation(double x, double y) {
		this.x = x;
		this.y = y;
	}
	
	public Point2D moveTowards(Point2D destination) {
	
		
		if (destination == null)
			return new Point2D.Double();
		
		double angle = Math.atan2(
			destination.getY() - getY(),
			destination.getX() - getX()
		);				
		 
		return	new Point2D.Double(Math.cos(angle), Math.sin(angle));	
	}
	
	public Point2D idleMovement() {
double fx = 0, fy = 0;
//Code inside the // is used for the random movement of the followers when they are idle
//////////////////////////////////////////////////////////////

if (Math.random() < randomBehaviorProb) {
	randHeading += Math.random() * turnRandomization*2 - turnRandomization;
	randVelocity += Math.random() * speedRandomization*2 - speedRandomization;				

	if (randVelocity < -0.5)
		randVelocity = -0.5f;
	if (randVelocity > 0.5)
		randVelocity = 0.5f;
	
}  

if (randVelocity !=0) {
	fx += randVelocity*Math.cos(randHeading);
	fy += randVelocity*Math.sin(randHeading);
}
///////////////////////////////////////////////////////////////////////


for (Agent p : SwarmState.getAllRobots()) {
	double d = distance(p);
	if (d == 0)
		continue;
	
	double f = 0;
	if (d >= R && d <= R * 1.5) {
		f = MainSwarmClass.g/(d*d*d);
		f = Math.min(MainSwarmClass.Fmax, f);
	}
	else if (d < R) {
		f = -MainSwarmClass.g/(d*d*d);
		f = Math.max(-MainSwarmClass.Fmax, f);
	}
	
	double angle = Math.atan2(
		p.getY() - getY(),
		p.getX() - getX()
	);
					
	fx += f * Math.cos(angle);
	fy += f * Math.sin(angle);
					
}



return new Point2D.Double(fx, fy);
}

	public double angleTo(Point2D pt) {
		return Math.atan2(pt.getY()-getY(), pt.getX()-getX());
	}

	public long getInteractCounter() {
		return interactCounter;
	}
}
